package com.addzero.web.ui.hooks.tree

import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import com.addzero.web.ui.hooks.tree.node_state.*
import com.addzero.web.ui.hooks.tree.node_state.NodeState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow

// 树形选择控件的视图模型
class TreeSelectViewModel<T>(
    private val initialNodes: List<TreeNode<T>>,
    private val isMultiSelect: Boolean = false,
    private val initialExpandedNodes: Set<String> = emptySet(),
) {
    private val _expandedNodes = mutableStateOf(initialExpandedNodes)
    val expandedNodes: State<Set<String>> = _expandedNodes

    internal val _selectedNodes = mutableStateOf(setOf<String>())
    val selectedNodes: State<Set<String>> = _selectedNodes

    private val _indeterminateNodes = mutableStateOf(setOf<String>())
    val indeterminateNodes: State<Set<String>> = _indeterminateNodes

    private val _searchText = MutableStateFlow("")
    val searchText: StateFlow<String> = _searchText.asStateFlow()

    private val _filteredNodes = mutableStateOf(initialNodes)
    val filteredNodes: State<List<TreeNode<T>>> = _filteredNodes

    private val _isEditMode = mutableStateOf(false)
    val isEditMode: State<Boolean> = _isEditMode

    // 更新搜索文本并过滤节点
    fun updateSearchText(text: String) {
        _searchText.value = text.lowercase()
        // 如果搜索文本为空，显示所有节点
        if (text.isEmpty()) {
            _filteredNodes.value = initialNodes
            return
        }
        // 过滤节点
        _filteredNodes.value = initialNodes.mapNotNull { node ->
            filterNode(node, text.lowercase())
        }
    }

    // 获取节点状态
    private fun getNodeState(node: TreeNode<T>): NodeState {
        if (node.children.isEmpty()) {
            return LeafNodeState()
        }

        val isSelected = _selectedNodes.value.contains(node.id)
        val isIndeterminate = _indeterminateNodes.value.contains(node.id)

        return when {
            isSelected -> NonLeafSelectedState()
            isIndeterminate -> NonLeafIndeterminateState()
            else -> NonLeafUnselectedState()
        }
    }

    // 更新父节点的选中状态
    private fun updateParentNodeStates(nodeId: String) {
        fun findParentNode(
            nodes: List<TreeNode<T>>, targetId: String, parentPath: List<TreeNode<T>> = emptyList(),
        ): List<TreeNode<T>>? {
            for (node in nodes) {
                if (node.children.any { it.id == targetId }) {
                    return parentPath + node
                }
                val result = findParentNode(node.children, targetId, parentPath + node)
                if (result != null) {
                    return result
                }
            }
            return null
        }

        val parentPath = findParentNode(initialNodes, nodeId)
        if (parentPath != null) {
            parentPath.forEach { parent ->
                val childrenIds = parent.children.map { it.id }.toSet()
                val selectedChildren = childrenIds.intersect(_selectedNodes.value)
                val indeterminateChildren = childrenIds.intersect(_indeterminateNodes.value)

                when {
                    selectedChildren.size == childrenIds.size -> {
                        _selectedNodes.value = _selectedNodes.value + parent.id
                        _indeterminateNodes.value = _indeterminateNodes.value - parent.id
                    }

                    selectedChildren.isEmpty() && indeterminateChildren.isEmpty() -> {
                        _selectedNodes.value = _selectedNodes.value - parent.id
                        _indeterminateNodes.value = _indeterminateNodes.value - parent.id
                    }

                    else -> {
                        _selectedNodes.value = _selectedNodes.value - parent.id
                        _indeterminateNodes.value = _indeterminateNodes.value + parent.id
                    }
                }
            }
        }
    }

    // 选择节点
    fun toggleSelection(nodeId: String) {
        val node = findNode(nodeId, initialNodes) ?: return
        val state = getNodeState(node)
        state.toggleSelection(node, this)
        updateParentNodeStates(nodeId)
    }

    // 切换节点展开/折叠状态
    fun toggleNode(nodeId: String) {
        _expandedNodes.value = if (_expandedNodes.value.contains(nodeId)) {
            _expandedNodes.value - nodeId
        } else {
            _expandedNodes.value + nodeId
        }
    }

    // 查找节点
    private fun findNode(nodeId: String, nodes: List<TreeNode<T>>): TreeNode<T>? {
        for (node in nodes) {
            if (node.id == nodeId) {
                return node
            }
            val found = findNode(nodeId, node.children)
            if (found != null) {
                return found
            }
        }
        return null
    }

    // 查找节点的所有兄弟节点ID（包括节点自身）
    private fun findSiblingIds(nodeId: String): Set<String> {
        fun findParentAndSiblings(nodes: List<TreeNode<T>>, targetId: String): Set<String> {
            for (node in nodes) {
                // 在当前节点的子节点中查找目标节点
                val targetInChildren = node.children.find { it.id == targetId }
                if (targetInChildren != null) {
                    // 找到目标节点，返回其所有兄弟节点的ID（包括自身）
                    return node.children.map { it.id }.toSet()
                }
                // 递归查找
                val result = findParentAndSiblings(node.children, targetId)
                if (result.isNotEmpty()) {
                    return result
                }
            }
            return emptySet()
        }

        return findParentAndSiblings(initialNodes, nodeId)
    }

    // 递归展开父节点
    private fun expandParentNodes(node: TreeNode<T>, expandedNodes: MutableSet<String>) {
        // 展开当前节点
        expandedNodes.add(node.id)
        // 递归展开所有包含匹配子节点的父节点
        node.children.forEach { child ->
            expandParentNodes(child, expandedNodes)
        }
    }

    // 递归过滤节点
    private fun filterNode(node: TreeNode<T>, searchText: String): TreeNode<T>? {
        if (node.label.lowercase().contains(searchText)) {
            return node
        }

        val filteredChildren = node.children.mapNotNull { child ->
            filterNode(child, searchText)
        }

        return if (filteredChildren.isNotEmpty()) {
            node.copy(children = filteredChildren)
        } else {
            null
        }
    }
}


